iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Security

Hack the Boyfriend: 為了 CTF 帥哥,我貢獻了我的肝臟系列 第 21

DLL - 我們來從頭了解你!

  • 分享至 

  • xImage
  •  

前言

昨天提到一大堆的名詞感覺不是很好懂,所以今天用比較簡單的方式科普一下 DLL 跟進行 DLL Injection 相關範例的說明。

什麼是 DLL?

DLL = Dynamic Link Library = 「動態連結函式庫」

可以想像它是程式的插件,裡面有一堆功能(函式 / 程式碼)。

而 Windows 上很多程式不會把所有功能都寫死在 EXE,而是用 DLL 來「模組化」。

舉理來說:

user32.dll:處理視窗、按鈕

kernel32.dll:處理記憶體、檔案

ws2_32.dll:處理網路

簡單說:

EXE 是主程式,DLL 就像輔助的外掛。

DLL Injection

如果能讓一個正常程式載入「惡意 DLL」,那駭客的程式碼就能假裝是這個程式的一部分來運行。

這樣就可以:

影響目標程式的行為、嘗試偷看/存取該程式有權限看的資料(例如注入到瀏覽器偷 cookie)、躲避防毒(因為看起來是「正常程式」在跑)~

DLL Injection 的白話流程

以最經典的 LoadLibrary 注入 為例:

  1. 找到目標程式 → 像找到一扇門(OpenProcess)。

  2. 在目標程式記憶體挖一塊空間 → 開一個小房間(VirtualAllocEx)。

  3. 把惡意 DLL 的路徑塞進去 → 把地址偷偷寫在小房間(WriteProcessMemory)。

  4. 告訴目標程式去載入它 → 像是指揮室下命令:「去讀這個 DLL!」(CreateRemoteThread 執行 LoadLibrary)。

  5. 目標程式乖乖幫忙載入惡意 DLL → 駭客的程式碼成功混進去了。

白話比喻:

就像把一張「假 ID 卡」偷偷塞進警衛室的資料夾裡,然後叫警衛自己去查 ~

結果警衛就幫忙把壞人放進去了。

DLL Hijacking(劫持)

這招是「利用 Windows 找 DLL 」的規則。

當程式要用一個 DLL 時,它會按照順序去找:

  • 應用程式目錄

  • 系統目錄

  • Windows 目錄

  • 當前目錄

  • PATH

如果程式只寫 LoadLibrary("abc.dll"),但沒有給完整路徑 = Windows 會自己嘗試自己去依照順序尋找。

攻擊者就可以「在應用程式目錄放一個假的 abc.dll」,結果程式就先載入了惡意版本。

白話比喻:

就像某人要找「咪寶」,但沒有指定是哪個咪寶

攻擊者就提前派一個「假咪寶」站在門口

結果被帶進去了。


在了解這兩個攻擊後,我們來看看 DLL Injection 範例!


DLL Injection 逐步解析範例

還記得我們昨天提到的 DLL Injection 範例嗎?

其實我們可以重新來看一下範例的編寫過程~

範例程式碼:

DWORD pid = 1234; // 目標 Process ID
char dllPath[] = "C:\\pwn\\evil.dll";

// 1. 打開目標程式
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

// 2. 在目標程式記憶體裡挖一塊空間
LPVOID remoteAddr = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);

// 3. 把 DLL 路徑寫進去
WriteProcessMemory(hProcess, remoteAddr, dllPath, strlen(dllPath), NULL);

// 4. 找到 LoadLibraryA 的位址
LPVOID loadLibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

// 5. 在目標程式裡建一個執行緒,去執行 LoadLibraryA(dllPath)
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibAddr, remoteAddr, 0, NULL);

逐步解析

Step 1. 找到目標程式 (OpenProcess)

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

意思:拿到目標程式的「鑰匙」。

pid = Process ID,目標程式的身分證。

PROCESS_ALL_ACCESS = 要求完全控制權。

成功後,hProcess 就是這扇門的把手。

Step 2. 在目標程式裡挖空間 (VirtualAllocEx)

LPVOID remoteAddr = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);

意思:在目標程式的記憶體裡,偷偷租了一間小房間。

strlen(dllPath) = 房間大小(剛好放下 DLL 路徑)。

PAGE_READWRITE = 設定成可讀可寫。

Step 3. 把 DLL 路徑寫進去 (WriteProcessMemory)

WriteProcessMemory(hProcess, remoteAddr, dllPath, strlen(dllPath), NULL);

意思:把「C:\pwn\evil.dll」這張小紙條塞進去。

這樣,等目標程式去讀這個記憶體位置時,就會看到要載入哪個 DLL。

Step 4. 找到 LoadLibraryA 的位址 (GetProcAddress)

LPVOID loadLibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

意思:翻出 Windows 自帶的 LoadLibraryA 這個功能的門牌號碼。

kernel32.dll = Windows 的系統 DLL,裡面有 LoadLibraryA。

LoadLibraryA 功能:幫你載入指定路徑的 DLL。

Step 5. 在目標程式裡建執行緒 (CreateRemoteThread)

HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibAddr, remoteAddr, 0, NULL);

意思:在目標程式裡新開一個小工人(Thread),命令它執行:

LoadLibraryA("C:\\pwn\\evil.dll")

最後...

結果:目標程式就自己幫忙載入了駭客的 DLL

當 evil.dll 被載入,裡面的 DllMain() 就會執行。

白話總結

OpenProcess = 找到目標程式,拿到控制權。

VirtualAllocEx = 在裡面開空間。

WriteProcessMemory = 寫入「要載入的 DLL 路徑」。

GetProcAddress = 找到「LoadLibrary」這個載入函式。

CreateRemoteThread = 讓目標程式自己執行「LoadLibrary(惡意DLL)」。

一切的目的:

把惡意 DLL 放進去,讓它在別人的程式裡執行。


小結

# 今天重新把昨天一部分的 DLL 拆解了,不過真正好玩的其實是 dll 裡面的東東(?)
# Anyway, 明天會繼續討論其他部分~

參考資源

Hack the box Academy


上一篇
DLL:獨自升級的日子
下一篇
聚會上的你
系列文
Hack the Boyfriend: 為了 CTF 帥哥,我貢獻了我的肝臟26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言